這篇文章會是參考這篇文章,並且濃縮出重點,最後也會有幾題測驗,方便驗收學習狀況,那麼我們進入今天的文章: Promise
Promise 通常會由 「生產者代碼」(producing code) 跟 「消費者代碼」(consuming code) 組成
通過網路加載數據的程式碼,例如: 餐廳
想要在"生產者代碼"完成工作的第一時間就能獲得其工作成果的程式碼,例如: 顧客
let promise = new Promise(function(resolve, reject) {
// executor
});
傳遞給 new Promise
的函數被稱為 executor
,executor
會在 new Promise
被創立時,自動執行
這邊可以看到有 resolve
跟 reject
兩個參數,分別代表成功或失敗
new Promise
除了會有 result
(resolve 或是 reject),還有 state
,代表該 Promise 的執行狀態
預設會是 pending
,resolve 被調用時變為 fulfilled
,或者在 reject 被調用時變為 rejected
。
任何一個 resolved
或 rejected
的 promise 都會被稱為 settled
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("…")); // 被忽略
setTimeout(() => resolve("…")); // 被忽略
});
這邊想說明的是不管是 resolve
還是 reject
,任何一個被觸發後,就會跳脫出 Promise,所以後面的 resolve
或是 reject
,就會被省略掉
剛剛有提到的 state 和 result 都只存活在該 Promise 中,一但離開了 Promise ,將不復存在,不過我們可以透過 .then()
、.catch()
去接收 result
p.then(onFulfilled, onRejected);
.then()
接受兩個參數,分別是 Promise 在成功及失敗情況時的回呼函式。
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(
result => alert(result),
error => alert(error)
);
.catch()
只會抓取 錯誤 (reject) 的 result
如果只對於錯誤 result 有興趣,有兩種方法
p.then(null, errorHandlingFunction) // 將 onFulfilled 設定為 null
p..catch(errorHandlingFunction)
finally
的功能是設置一個處理程式在前面的操作完成後,執行清理/終結。finally
的執行時間是在 promise settled
時就會執行:無論 promise 的result 是 resolve 還是 reject。
這邊分享四題我覺得還不錯的考題,給各位讀者做練習
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
答案:
1 -> 2 -> 4 -> 3
原因是因為 Promise 構造函數是同步執行的,promise.then 中的函數是異步執行的
const first = () => (new Promise((resolve, reject) => {
console.log(3);
let p = new Promise((resolve, reject) => {
console.log(7);
setTimeout(() => {
console.log(5);
resolve(6);
}, 0)
resolve(1);
});
resolve(2);
p.then((arg) => {
console.log(arg);
});
}));
first().then((arg) => {
console.log(arg);
});
console.log(4);
答案:
3 -> 7 -> 4 -> 1 -> 2 -> 5
相信大家基本上都能答出 3 -> 7 -> 4 ,至於後面的 1 -> 2 -> 5 是因為 setTimeout 是一個 Macrotask 他會先被放到 task queue 中,等待 Microtask 都執行完成才會被丟到 call stack 中執行
如果不清楚 macrotask 跟 microtask 的讀者,可以參考我之前的文章
const promise = new Promise((resolve, reject) => {
resolve('success1')
reject('error')
resolve('success2')
})
promise
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
答案:
then: success1
原因是因為 Promise 中的 resolve 或 reject 只有第一次執行有效,所以後面的都會被省略
4. 請問下方程式碼會 console 出什麼?
Promise.resolve(1)
.then((res) => {
console.log(res)
return 2
})
.catch((err) => {
return 3
})
.then((res) => {
console.log(res)
})
答案:
1 2
原因是因為 Promise 可以鏈式調用。
Promise 每次調用 .then 或者 .catch 都會返回一個新的 Promise,從而實現了鏈式調用。
至於不是 1 3 的原因是因為是 resolve
可以想像成
Promise.resolve(1)
.then((res) => {
console.log(res)
return 2
})
Promise.resolve(2)
.then((res) => {
console.log(res)
})
以上就是今天 Promise 的介紹,文章最後還是推薦各位讀者可以去看看JavaScript.info 的文章
文章同步發佈在我的 Medium ,有興趣的讀者可以去看看
以上就是今天的文章,如果有任何錯誤,或是問題都歡迎留言給我,那我們下次見,掰掰
參考文章:
https://javascript.info/promise-basics